package com.zfei.gfb.device.web.filter;

import com.zfei.gfb.bean.Status;
import com.zfei.gfb.core.Context;
import com.zfei.gfb.util.Https;
import com.zfei.gfb.util.Trace;
import com.zfei.gfb.util.WebLogBean;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author fgh
 */
@Component
public class ContextFilter extends OncePerRequestFilter {

    public static final String HANDLER_ERROR = "com.news.device.web.filter.ContextFilter.HANDLER_ERROR";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        boolean isFirstRequest = !isAsyncDispatch(request);
        HttpServletRequest requestToUse = request;

        if (isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) {
            requestToUse = new ContentCachingRequestWrapper(request);
        }

        boolean shouldLog = shouldLog(requestToUse, response);
        if (shouldLog && isFirstRequest) {
            beforeRequest(requestToUse, response);
        }
        try {
            filterChain.doFilter(requestToUse, response);
        } finally {
            if (shouldLog && !isAsyncStarted(requestToUse)) {
                afterRequest(requestToUse, response);
            }
        }
    }

    protected boolean shouldLog(HttpServletRequest request, HttpServletResponse response) {
        return true;
    }

    protected void beforeRequest(HttpServletRequest request, HttpServletResponse response) {
        Context.ROOT.fork().attach();
        WebLogBean.start();
        WebLogBean logBean = WebLogBean.getLogBean();
        logBean.setTrace(Trace.start(logBean.getBeginTime()));
        logBean.setPath(request.getRequestURI());
        logBean.setClientIp(Https.getIp(request));
        logBean.setHeaders(Https.getHeaders(request));
        logBean.setParams(request.getParameterMap());
    }

    protected void afterRequest(HttpServletRequest request, HttpServletResponse response) {
        handleContext();
        Trace.stop();
        WebLogBean.stop();
        Context.removeContext();
    }

    protected void handleContext() {
        if (Context.current().getAttachment(HANDLER_ERROR) != null) {
            WebLogBean logBean = WebLogBean.getLogBean();
            logBean.setCode(Status.GONE.value());
            logBean.setError("Handler Error,"+ Context.current().getAttachment(HANDLER_ERROR));
        }
    }
}
